package com.yeyaomai.dksns.flowis.mongoutil;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.data.mongodb.core.MongoTemplate;

import com.mongodb.AggregationOutput;
import com.mongodb.BasicDBObject;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;

/**
 * mongo查询工具包
 * 
 * @author zuoshuaiok@gmail.com
 * 
 */
public class MongoHandlerTookit {

	private static MongoClient client;

	private static DBCollection collection = null;
	static {
		try {
			// 生产并非用此处初始化，取得是spring提供的数据源，此处用来单元测试
			client = new MongoClient("localhost", 20001);
			collection = client.getDB("ShopBase").getCollection("bizCard");
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			System.err.println("-----找不到服务器");
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		DB flow_db = client.getDB("ShopBase");
		collection = flow_db.getCollection("bizCard");
		// 查找一个
		// findOne(collection);
		// 遍历整个
		// getTheCollectionDetail(collection);
		// 简单查询
		// SimpleSearch(collection);
//		long st = System.currentTimeMillis();
//		getAggregateResults(collection);
//		long et = System.currentTimeMillis();
//		System.err.println((et - st) / 1000);
		Where where=new Where();
		where.setKey("createTime").setLt(new Date());
		List<Where> wherelistList=new ArrayList<Where>();
		wherelistList.add(where);
		GroupByResults(new BaseQuery().setSelect("title,url,"+GlobalStatus.COUNT.forField("title")).setWhereList(wherelistList).setGroupBy("city"), collection);
		
	}

	private static boolean checkNullObject(Object param) {
		return null != param;
	}

	private static boolean checkGroupType(String param) {
		return param.indexOf(":") > 0;
	}

	public static CommandResult GroupByResults(BaseQuery query, DBCollection collection) {

		List<Where> whereList = query.getWhereList();
		String[] search_fields = query.getSelect().trim().split(",");
		String[] group_fields = query.getGroupBy().trim().split(",");

		DBObject matches = new BasicDBObject();
		for (Where where : whereList) {
			if (checkNullObject(where.getEq())) {
				matches.put(where.getKey(), where.getEq());
			} else if ((checkNullObject(where.getLt()) || checkNullObject(where.getLte()))
					&& (checkNullObject(where.getGt()) || checkNullObject(where.getGte()))) {
				boolean flag = checkNullObject(where.getLt());
				boolean flag_gt = checkNullObject(where.getGt());
				matches.put(where.getKey(), new BasicDBObject(flag ? "$lt" : "$lte", flag ? where.getLt() : where.getLte())
						.append(flag_gt ? "$gt" : "$gte", flag_gt ? where.getGt() : where.getGte()));
			} else if (checkNullObject(where.getLt()) || checkNullObject(where.getLte())) {
				boolean flag = checkNullObject(where.getLt());
				matches.put(where.getKey(), new BasicDBObject(flag ? "$lt" : "$lte", flag ? where.getLt() : where.getLte()));
			} else if ((checkNullObject(where.getGt())) || checkNullObject(where.getGte())) {
				boolean flag = checkNullObject(where.getGt());
				matches.put(where.getKey(), new BasicDBObject(flag ? "$gt" : "$gte", flag ? where.getGt() : where.getGte()));
			} else {
				System.out.println("----无合适匹配或者无匹配");
			}
		}
		DBObject match = new BasicDBObject("$match", matches);

		DBObject fields_project = new BasicDBObject();

		for (int i = 0; i < search_fields.length; i++) {
			if (checkGroupType(search_fields[i]))
				fields_project.put(search_fields[i].split(":")[1], 1);
			else {
				fields_project.put(search_fields[i], 1);
			}
		}

		for (int i = 0; i < group_fields.length; i++) {
			fields_project.put(group_fields[i], 1);
		}

		DBObject project = new BasicDBObject("$project", fields_project);

		DBObject fields_group = new BasicDBObject();
		for (int i = 0; i < group_fields.length; i++) {
			fields_group.put(group_fields[i], "$" + group_fields[i]);
		}

		DBObject groupFields = new BasicDBObject("_id", fields_group);
		for (int i = 0; i < search_fields.length; i++) {
			if (query.getGroupBy().indexOf(search_fields[i]) == -1) {

				if (checkGroupType(search_fields[i])) {
					String[] search = search_fields[i].split(":");
					if (search[0].equals(GlobalStatus.COUNT.name))
						groupFields.put(search[1], new BasicDBObject("$sum", 1));
					else {
						groupFields.put(search[1], new BasicDBObject(search[0], "$" + search[1]));
					}
				} else {
					groupFields.put(search_fields[i], new BasicDBObject("$min", ("$" + search_fields[i])));
				}
			}
		}
		DBObject group = new BasicDBObject("$group", groupFields);
		// run aggregation
		AggregationOutput output = collection.aggregate(match, project, group);
		return output.getCommandResult();
	}

	private static void getAggregateResults(DBCollection collection) {

		// Where access_city=...
		// create our pipeline operations, first with the $match
		// DBObject match = new BasicDBObject("$match", new BasicDBObject(
		// "access_city", "郑州市"));
		DBObject matches = new BasicDBObject();

		// matches.put("access_city", "郑州市");
//		matches.put("ip", "125.46.215.250");
//		matches.put("access_date", new BasicDBObject("$gt", "2012-07-04"));
		// matches.put("req_source", new BasicDBObject("$gt", 1).append("$lte",
		// 5));

		DBObject match = new BasicDBObject("$match", matches);
		// DBObject match1 = new BasicDBObject("$match", new BasicDBObject(
		// "access_city", "杭州市"));
		// select req_source , ip,access_city from flowisDetail ...
		// build the $projection operation
		DBObject fields = new BasicDBObject();
		// fields.put("req_source", 1);
		// fields.put("ip", 1);
		// fields.put("returnNumber", 1);
		// fields.put("internet_provider", 1);
//		fields.put("cookieId", 1);
//		fields.put("access_date", 1);
//		fields.put("stoptime", 1);
		fields.put("site", 1);
		fields.put("siteId", 1);
		DBObject project = new BasicDBObject("$project", fields);
		// group by ip...
		// Now the $group operation

		DBObject fieldsGroup = new BasicDBObject();
//		fieldsGroup.put("cookieId", "$cookieId");
		fieldsGroup.put("site", "$site");
		fieldsGroup.put("siteId", "$siteId");
		DBObject groupFields = new BasicDBObject("_id", fieldsGroup);

		// groupFields.put("_id", _id);
		groupFields.put("site", new BasicDBObject("$min", "$site"));
		// groupFields.put("averages", new BasicDBObject("$sum", 1));
		groupFields.put("siteId", new BasicDBObject("$sum", "1"));
		// groupFields.put("internet_provider", new BasicDBObject("$min",
		// "$internet_provider"));
		DBObject group = new BasicDBObject("$group", groupFields);

		// run aggregation
		AggregationOutput output = collection.aggregate(match, project, group);

//		System.out.println(output.results());

		Map<String, Object> objmap = ParseJsonUtil.parseJSON2Map(output.results().toString().replace("]", "")
				.replace("[", ""));
		System.out.println(objmap.size());
		for (Entry<String, Object> entry : objmap.entrySet()) {
			System.out.println(entry.getKey() + "---" + entry.getValue());
		}
	}

	/**
	 * 按条件查询
	 * 
	 * @param collection
	 */
	private static void SimpleSearch(DBCollection collection) {
		BasicDBObject query = new BasicDBObject("access_city", "郑州市");

		DBCursor cursor = collection.find(query);

		while (cursor.hasNext()) {
			DBObject dbObject = (DBObject) cursor.next();
			System.out.println(dbObject);
		}
	}

	/**
	 * 查找一个
	 * 
	 * @param collection
	 */
	private static void findOne(DBCollection collection) {
		DBObject obj = collection.findOne();
		System.out.println(obj);
	}

	/**
	 * 遍历集合的全部数据
	 * 
	 * @param collection
	 */
	private static void getTheCollectionDetail(DBCollection collection) {
		DBCursor cursor = collection.find();
		while (cursor.hasNext()) {
			DBObject dbObject = (DBObject) cursor.next();
			System.out.println(dbObject);
		}
	}

}
